package observer

import (
	"fmt"
)

type Subject struct {
	obs []Observer
	ctx string
}

type SubjectItf interface {
	Attach(Observer)
	DeAttach(Observer)
}

func NewSubject() *Subject {
	return &Subject{
		obs: make([]Observer, 0),
	}
}

func (s *Subject) Attach(ob Observer) {
	s.obs = append(s.obs, ob)
	fmt.Printf("add observer: %#v\n", ob)
	ob.Update(s)
}

func (s *Subject) DeAttach(ob Observer) {
	fmt.Printf("rmv observer: %#v\n", ob)

	for i, o := range s.obs {
		if o != ob {
			continue
		}
		s.obs = append(s.obs[:i], s.obs[i+1:]...)
		fmt.Printf("rmv observer: %#v succ\n", ob)
	}
}

func (s *Subject) notify() {
	for _, o := range s.obs {
		o.Update(s)
	}
}

func (s *Subject) updateContext(ctx string) {
	if ctx == s.ctx {
		fmt.Printf("not change the status")
		return
	}
	s.ctx = ctx
	s.notify()
}

// can be a observer
type Observer interface {
	Update(*Subject)
}

type Reader struct {
	name string
}

func NewReader(name string) *Reader {
	return &Reader{
		name: name,
	}
}

func (r *Reader) Update(s *Subject) {
	fmt.Printf("%s receive %s\n", r.name, s.ctx)
}
